package com.bringway.framework.util.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

import org.apache.commons.net.ftp.FTPClient;




public class Ftp {
	/** FTP文件路径分隔符 */
	public final static char separator = '/';

	/** 本地文件路径分隔符 */
	public final static char localSeparator = File.separatorChar;

	/** 非本地文件路径分隔符的斜杆 */
	public final static char localSeparatorN = localSeparator == '\\' ? '/'
			: '\\';

	private FTPClient ftp;

	private String host;

	private int port;

	private String userName;

	private String PassWord;

	/**
	 * @param ip
	 *            机器IP
	 * @param port
	 *            机器FTP端口号
	 * @param username
	 *            FTP用户名
	 * @param password
	 *            FTP密码
	 * @throws Exception
	 */
	public Ftp(String ip, int port, String username, String password)
			throws IOException {
		this.host = ip;
		this.port = port;
		this.ftp = new FTPClient();
		this.userName = username;
		this.PassWord = password;
	}

	/**
	 * @see Ftp#Ftp(String, int, String, String)
	 */
	public Ftp(String ip, String username, String password) throws IOException {
		this.host = ip;
		this.port = 21;
		this.ftp = new FTPClient();
		this.userName = username;
		this.PassWord = password;
	}

	/** FTP上路径以/分隔 */
	String normalizeRemotePath(String remote) {
		if (remote.indexOf('\\') == -1)
			return remote;
		return remote.replace('\\', '/');
	}

	/** 本地文件路径格式化 */
	String normalizeLocalPath(String local) {
		return local.replace(localSeparatorN, localSeparator);
	}

	/**
	 * 登录FTP
	 */
	public void login() throws IOException {
		ftp.connect(this.host, this.port);
		ftp.login(userName, PassWord);
		if (ftp.getReplyCode() == 530) {
			try {
				throw new RuntimeException("530: Not logged in. 不能正常登陆!");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (ftp.getReplyCode() == 550) {
			try {
				throw new RuntimeException("550: Permission denied! 没有权限");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 退出FTP
	 */
	public boolean logout() {
		// 用ftp.closeServer()断开FTP出错时用下更语句退出??
		try {
			ftp.logout();
			ftp.disconnect(); // 取得服务器的返回信息
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	protected void finalize() throws Throwable {
		try {
			logout();
		} catch (Exception e) {
		}
	}

	public void buildPath(String path) throws IOException {
		path = normalizeRemotePath(path);
		StringTokenizer s = new StringTokenizer(path, "/"); // sign
		String pathName = "";
		while (s.hasMoreElements()) {
			String dir = ((String) s.nextElement()).trim();
			if ("".equals(dir))
				continue;
			pathName = pathName + "/" + (String) dir;
			try {
				ftp.makeDirectory(pathName + "\r\n");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 列出Path路径下的文件
	 */
	public ArrayList listFiles(String path) throws IOException {
		path = normalizeRemotePath(path);
		ftp.changeWorkingDirectory(path);
		String[] list = ftp.listNames();
		ArrayList result = new ArrayList();
		result.addAll(Arrays.asList(list));
		return result;
	}

	/**
	 * 列出Path路径下的文件<br>
	 * 需要设置服务器编码格式的<br>
	 * 一般情况windows下为GBK,linux 下为UTF-8即可<br>
	 * 
	 */
	public ArrayList listFiles(String path, String encoding) throws IOException {
		path = normalizeRemotePath(path);
		ftp.changeWorkingDirectory(path);
		ftp.setControlEncoding(encoding);
		String[] list = ftp.listNames();
		ArrayList result = new ArrayList();
		result.addAll(Arrays.asList(list));
		return result;
	}

	public void uploadFile(String local, String remote) throws IOException {
		local = normalizeLocalPath(local);
		uploadFile(new FileInputStream(local), remote);
	}

	public synchronized void uploadFile(File file, String remote)
			throws IOException {
		uploadFile(new FileInputStream(file), remote);
	}

	/**
	 * 从流中上传文件
	 * 
	 * @param in
	 *            输入流, 将被关闭
	 * @param remote
	 *            远程路径
	 * @throws IOException
	 */
	public synchronized void uploadFile(InputStream in, String remote)
			throws IOException {
		remote = normalizeRemotePath(remote);
		String path = remote.substring(0, remote.lastIndexOf("/"));
		String filename = remote.substring(remote.lastIndexOf("/") + 1);
		// buildPath(path);
		ftp.changeWorkingDirectory(path);
		ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
		ftp.storeFile(filename, in);
	}

	/**
	 * 得到输出流
	 * 
	 * @param remote
	 *            远程路径
	 * @throws IOException
	 */
	public OutputStream getOutputStream(String remote) throws IOException {
		remote = normalizeRemotePath(remote);
		String path = remote.substring(0, remote.lastIndexOf("/"));
		String filename = remote.substring(remote.lastIndexOf("/") + 1);
		// buildPath(path);
		ftp.changeWorkingDirectory(path);
		ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
		return ftp.storeFileStream(filename);
	}

	/**
	 * 得到输入流
	 * 
	 * @param remote
	 * @return
	 * @throws IOException
	 *             InputStream
	 */
	public InputStream getInputStream(String remote) throws IOException {
		remote = normalizeRemotePath(remote);
		String path = remote.substring(0, remote.lastIndexOf("/"));
		String filename = remote.substring(remote.lastIndexOf("/") + 1);
		// buildPath(path);
		ftp.changeWorkingDirectory(path);
		ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
		return ftp.retrieveFileStream(filename);
	}

	public void downFile(String remote, OutputStream out) throws IOException {
		remote = normalizeRemotePath(remote);
		String path = remote.substring(0, remote.lastIndexOf("/"));
		String filename = remote.substring(remote.lastIndexOf("/") + 1);
		ftp.changeWorkingDirectory(path);
		ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
		ftp.retrieveFile(filename, out);
	}

	public boolean deleteFile(String remote) throws IOException {
		remote = normalizeRemotePath(remote);
		String path = remote.substring(0, remote.lastIndexOf("/"));
		String filename = remote.substring(remote.lastIndexOf("/") + 1);
		ftp.changeWorkingDirectory(path);
		ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
		return ftp.deleteFile(filename);

	}
}
